GtkApplicationWindow: give up on handling dispose
authorRyan Lortie <desrt@desrt.ca>
Tue, 14 Jan 2014 15:33:13 +0000 (10:33 -0500)
committerRyan Lortie <desrt@desrt.ca>
Tue, 14 Jan 2014 15:41:35 +0000 (10:41 -0500)
Stop trying to deal with "theoretical possibilities".

We can't possibly continue to be a faithful GActionGroup implementation
across dispose because dispose has a side effect of removing everyone's
signal handlers.

The code that we ran after the dispose chainup to do all of the fancy
signal emulation was therefore dead.  The test that aimed to verify this
was buggy itself due to an uninitialised variable, so really, it never
worked at all.

We keep the re-ordering of the chainup from the original commit to avoid having
trouble with GtkActionMuxer and keep the checks in place that will prevent an
outright segfault in the case that someone else tries to use the interface
post-dispose.

https://bugzilla.gnome.org/show_bug.cgi?id=722189

gtk/gtkapplicationwindow.c
testsuite/gtk/Makefile.am
testsuite/gtk/gtkapplicationwindow.c [deleted file]

index 4e2a1b76acd74ac052aa20cc635751569c953829..93f126749e4607f7a0ddd5793d3ad56ef02a6aa7 100644 (file)
@@ -771,50 +771,9 @@ gtk_application_window_dispose (GObject *object)
    * handler of GtkWindow).
    *
    * That reduces our chances of being watched as a GActionGroup from a
-   * muxer constructed by GtkApplication.  Even still, it's
-   * theoretically possible that someone else could be watching us.
-   * Therefore, we have to take care to ensure that we don't violate our
-   * obligations under the interface of GActionGroup.
-   *
-   * The easiest thing is just for us to act as if all of the actions
-   * suddenly disappeared.
+   * muxer constructed by GtkApplication.
    */
-  if (window->priv->actions)
-    {
-      gchar **action_names;
-      guint signal;
-      gint i;
-
-      /* Only send the remove signals if someone is listening */
-      signal = g_signal_lookup ("action-removed", G_TYPE_ACTION_GROUP);
-      if (signal && g_signal_has_handler_pending (window, signal, 0, TRUE))
-        /* need to send a removed signal for each action */
-        action_names = g_action_group_list_actions (G_ACTION_GROUP (window->priv->actions));
-      else
-        /* don't need to send signals: nobody is watching */
-        action_names = NULL;
-
-      /* Free the group before sending the signals for two reasons:
-       *
-       *  1) we want any incoming calls to see an empty group
-       *
-       *  2) we don't want signal handlers that trigger in response to
-       *     the action-removed signals that we're firing to attempt to
-       *     modify the action group in a way that may cause it to fire
-       *     additional signals (which we would then propagate)
-       */
-      g_object_unref (window->priv->actions);
-      window->priv->actions = NULL;
-
-      /* It's safe to send the signals now, if we need to. */
-      if (action_names)
-        {
-          for (i = 0; action_names[i]; i++)
-            g_action_group_action_removed (G_ACTION_GROUP (window), action_names[i]);
-
-          g_strfreev (action_names);
-        }
-    }
+  g_clear_object (&window->priv->actions);
 }
 
 static void
index daefbffe7d52ad12a20df502cab531be43ed2e3e..077b4f3b108ae216a695c93f5fb6fcc8ae2a8e7f 100644 (file)
@@ -39,7 +39,6 @@ TEST_PROGS +=                         \
        floating                \
        grid                    \
        gtkmenu                 \
-       gtkapplicationwindow    \
        keyhash                 \
        listbox                 \
        no-gtk-init             \
diff --git a/testsuite/gtk/gtkapplicationwindow.c b/testsuite/gtk/gtkapplicationwindow.c
deleted file mode 100644 (file)
index fa5f743..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#include <gtk/gtk.h>
-
-static void
-removed (GActionGroup *group,
-         const gchar  *name,
-         gpointer      user_data)
-{
-  gboolean *was_removed = user_data;
-
-  *was_removed = TRUE;
-}
-
-static void
-test_as_actiongroup (void)
-{
-  GSimpleAction *action;
-  gboolean was_removed;
-  gpointer window;
-  gchar **list;
-
-  /* do a dummy round... */
-  window = g_object_ref_sink (g_object_new (GTK_TYPE_APPLICATION_WINDOW, NULL));
-  gtk_widget_destroy (window);
-  g_object_unref (window);
-
-  /* create a window, add an action */
-  window = g_object_ref_sink (g_object_new (GTK_TYPE_APPLICATION_WINDOW, NULL));
-  action = g_simple_action_new ("foo", NULL);
-  g_action_map_add_action (window, G_ACTION (action));
-  g_object_unref (action);
-
-  /* check which actions we have in the group */
-  list = g_action_group_list_actions (window);
-  g_assert_cmpstr (list[0], ==, "foo");
-  g_assert_cmpstr (list[1], ==, NULL);
-  g_strfreev (list);
-
-  /* make sure that destroying the window keeps our view of the actions
-   * consistent.
-   */
-  g_signal_connect (window, "action-removed", G_CALLBACK (removed), &was_removed);
-  gtk_widget_destroy (window);
-
-  /* One of two things will have happened, depending on the
-   * implementation.  Both are valid:
-   *
-   *  - we received a signal that the action was removed when we
-   *    destroyed the window; or
-   *
-   *  - the action is still available.
-   *
-   * Make sure we're in one of those states.
-   *
-   * This additionally ensures that calling into methods on the window
-   * will continue to work after it has been destroy (and not segfault).
-   */
-  list = g_action_group_list_actions (window);
-
-  if (was_removed == FALSE)
-    {
-      /* should still be here */
-      g_assert_cmpstr (list[0], ==, "foo");
-      g_assert_cmpstr (list[1], ==, NULL);
-    }
-  else
-    /* should be gone */
-    g_assert_cmpstr (list[0], ==, NULL);
-
-  g_object_unref (window);
-  g_strfreev (list);
-}
-
-int
-main (int argc, char **argv)
-{
-  gtk_test_init (&argc, &argv, NULL);
-
-  g_test_add_func ("/gtkapplicationwindow/as-actiongroup", test_as_actiongroup);
-
-  return g_test_run ();
-}